/*
tms
它的原理是定义好链接模板类型，有三个参数，是需要计算的
传给urlTemplateImageryProvider计算，最后根据链接样式展现图片
cesium是创建的相对路径，即识别为image()方式加载
我们的数据是存在数据库无相对路径，cesium提供了loadCRN（将给定的URL异步加载和解析到CRN文件或解析CRN文件的原始二进制数据）,loadKTX（将给定的URL异步加载并解析为KTX文件或解析KTX文件的原始二进制数据。）

 */
//  1. 分离（定义出网页格式的）出createTileMapServiceImageryProvider    更名为    TMSImageryProvider
var TMSImageryProvider = function(options){
    var defaultCredit = new Cesium.Credit('TMS');
    options = Cesium.defaultValue(options, {});
    if (! Cesium.defined(options.url)) {
        throw new  Cesium.DeveloperError('options.url is required.');
    }
    var url = options.url;

    var proxy = options.proxy;
    var fileExtension = Cesium.defaultValue(options.fileExtension, 'png');
    var tilingScheme =new Cesium.GeographicTilingScheme(Cesium.Ellipsoid.WGS84);
    var rectangle = Cesium.defaultValue(options.rectangle,tilingScheme.rectangle);

    var tileWidth = Cesium.defaultValue(options.tileWidth,256);
    var tileHeight = Cesium.defaultValue(options.tileHeight,256);
    var minimumLevel = Cesium.defaultValue(options.minimumLevel, 0);
    var maximumLevel = Cesium.defaultValue(options.maximumLevel, 13);
    
   var credit = Cesium.defaultValue(options.credit, defaultCredit);

// var tileDiscardPolicy = new Cesium.TileDiscardPolicy();
   
    if (typeof credit === 'string') {
        credit = new Cesium.Credit(credit);
    }
    this._credit = credit;

    if (rectangle.west < tilingScheme.rectangle.west) {
        rectangle.west = tilingScheme.rectangle.west;
    }
    if (rectangle.east > tilingScheme.rectangle.east) {
        rectangle.east = tilingScheme.rectangle.east;
    }
    if (rectangle.south < tilingScheme.rectangle.south) {
        rectangle.south = tilingScheme.rectangle.south;
    }
    if (rectangle.north > tilingScheme.rectangle.north) {
        rectangle.north = tilingScheme.rectangle.north;
    }

    var templateUrl = Cesium.joinUrls(url, '{z}/{x}/{reverseY}.' + fileExtension);

    var imageryProvider = new Cesium.UrlTemplateImageryProvider({
                    url: templateUrl,
                    tilingScheme: tilingScheme,
                    rectangle: rectangle,
                    tileWidth: tileWidth,
                    tileHeight: tileHeight,
                    minimumLevel: minimumLevel,
                    maximumLevel: maximumLevel,
                    proxy: options.proxy,
                    tileDiscardPolicy: options.tileDiscardPolicy,
                    credit: options.credit
                });
    return imageryProvider;
}


// var TemplateImageryProvider = function(options){

//             if (!Cesium.defined(options)) {
//                 throw new Cesium.DeveloperError('options is required.');
//             }


//             this._errorEvent = new Event();   //创建一个新事件   _errorEvent
//             //清空用到的对象属性（名称），确保传来的属性不被原来的占用空间
//             this._url = undefined;  //url  
//             this._urlSchemeZeroPadding = undefined;
//             this._pickFeaturesUrl = undefined;
//             this._proxy = undefined;
//             this._tileWidth = undefined;
//             this._tileHeight = undefined;
//             this._maximumLevel = undefined;
//             this._minimumLevel = undefined;
//             this._tilingScheme = undefined;
//             this._rectangle = undefined;
//             this._tileDiscardPolicy = undefined;
//             this._credit = undefined;
//             this._hasAlphaChannel = undefined;
//             this._readyPromise = undefined;

            
//             this.enablePickFeatures = true;

//             this.reinitialize(options);
//         }

//         Cesium.defineProperties(TemplateImageryProvider.prototype, {
           
//             url: {
//                 get: function () {
//                     return this._url;
//                 }
//             },

            
//             urlSchemeZeroPadding: {
//                 get: function () {
//                     return this._urlSchemeZeroPadding;
//                 }
//             },


            
//             pickFeaturesUrl: {
//                 get: function () {
//                     return this._pickFeaturesUrl;
//                 }
//             },

            
//             proxy: {
//                 get: function () {
//                     return this._proxy;
//                 }
//             },

            
//             tileWidth: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new Cesium.DeveloperError('tileWidth must not be called before the imagery provider is ready.');
//                     }
//                     return this._tileWidth;
//                 }
//             },

//             tileHeight: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new Cesium.DeveloperError('tileHeight must not be called before the imagery provider is ready.');
//                     }
//                     return this._tileHeight;
//                 }
//             },

//             maximumLevel: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new Cesium.DeveloperError('maximumLevel must not be called before the imagery provider is ready.');
//                     }
//                     return this._maximumLevel;
//                 }
//             },

//             minimumLevel: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new Cesium.DeveloperError('minimumLevel must not be called before the imagery provider is ready.');
//                     }
//                     return this._minimumLevel;
//                 }
//             },

//             tilingScheme: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new Cesium.DeveloperError('tilingScheme must not be called before the imagery provider is ready.');
//                     }
//                     return this._tilingScheme;
//                 }
//             },

//             rectangle: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new Cesium.DeveloperError('rectangle must not be called before the imagery provider is ready.');
//                     }
//                     return this._rectangle;
//                 }
//             },

      
//             tileDiscardPolicy: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new Cesium.DeveloperError('tileDiscardPolicy must not be called before the imagery provider is ready.');
//                     }
//                     return this._tileDiscardPolicy;
//                 }
//             },

//             errorEvent: {
//                 get: function () {
//                     return this._errorEvent;
//                 }
//             },

//             ready: {
//                 get: function () {
//                     return Cesium.defined(this._urlParts);
//                 }
//             },

     
//             readyPromise: {
//                 get: function () {
//                     return this._readyPromise;
//                 }
//             },

//             credit: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new Cesium.DeveloperError('credit must not be called before the imagery provider is ready.');
//                     }
//                     return this._credit;
//                 }
//             },

//             hasAlphaChannel: {
//                 get: function () {
//                     if (!this.ready) {
//                         throw new DeveloperError('hasAlphaChannel must not be called before the imagery provider is ready.');
//                     }
//                     return this._hasAlphaChannel;
//                 }
//             }
//         });

        
//         TemplateImageryProvider.prototype.reinitialize = function (options) {
//             var that = this;
//             that._readyPromise = when(options).then(function (properties) {
//                 if (!Cesium.defined(properties)) {
//                     throw new Cesium.DeveloperError('options is required.');
//                 }
//                 if (!Cesium.defined(properties.url)) {
//                     throw new Cesium.DeveloperError('options.url is required.');
//                 }
//                 that.enablePickFeatures = defaultValue(properties.enablePickFeatures, that.enablePickFeatures);
//                 that._url = properties.url;
//                 that._urlSchemeZeroPadding = defaultValue(properties.urlSchemeZeroPadding, that.urlSchemeZeroPadding);
//                 that._pickFeaturesUrl = properties.pickFeaturesUrl;
//                 that._proxy = properties.proxy;
//                 that._tileDiscardPolicy = properties.tileDiscardPolicy;
//                 that._getFeatureInfoFormats = properties.getFeatureInfoFormats;

//                 that._subdomains = properties.subdomains;
//                 if (isArray(that._subdomains)) {
//                     that._subdomains = that._subdomains.slice();
//                 } else if (defined(that._subdomains) && that._subdomains.length > 0) {
//                     that._subdomains = that._subdomains.split('');
//                 } else {
//                     that._subdomains = ['a', 'b', 'c'];
//                 }

//                 that._tileWidth = defaultValue(properties.tileWidth, 256);
//                 that._tileHeight = defaultValue(properties.tileHeight, 256);
//                 that._minimumLevel = defaultValue(properties.minimumLevel, 0);
//                 that._maximumLevel = properties.maximumLevel;
//                 that._tilingScheme = defaultValue(properties.tilingScheme, new WebMercatorTilingScheme({ellipsoid: properties.ellipsoid}));
//                 that._rectangle = defaultValue(properties.rectangle, that._tilingScheme.rectangle);
//                 that._rectangle = Rectangle.intersection(that._rectangle, that._tilingScheme.rectangle);
//                 that._hasAlphaChannel = defaultValue(properties.hasAlphaChannel, true);

//                 var credit = properties.credit;
//                 if (typeof credit === 'string') {
//                     credit = new Credit(credit);
//                 }
//                 that._credit = credit;

//                 that._urlParts = urlTemplateToParts(that._url, tags);
//                 that._pickFeaturesUrlParts = urlTemplateToParts(that._pickFeaturesUrl, pickFeaturesTags);
//                 return true;
//             });
//         };

//         /**
//          * Gets the credits to be displayed when a given tile is displayed.
//          *
//          * @param {Number} x The tile X coordinate.
//          * @param {Number} y The tile Y coordinate.
//          * @param {Number} level The tile level;
//          * @returns {Credit[]} The credits to be displayed when the tile is displayed.
//          *
//          * @exception {DeveloperError} <code>getTileCredits</code> must not be called before the imagery provider is ready.
//          */
//        TemplateImageryProvider.prototype.getTileCredits = function (x, y, level) {
//             if (!this.ready) {
//                 throw new Cesium.DeveloperError('getTileCredits must not be called before the imagery provider is ready.');
//             }
//             return undefined;
//         };

//        TemplateImageryProvider.prototype.requestImage = function (x, y, level, distance) {
//             if (!this.ready) {
//                 throw new Cesium.DeveloperError('requestImage must not be called before the imagery provider is ready.');
//             }
//             var url = buildImageUrl(this, x, y, level);
//             //console.log(x,y,level,distance)
//             //console.log(url)
//             return Cesium.ImageryProvider.loadImage(this, url, distance);
//         };

//         TemplateImageryProvider.prototype.pickFeatures = function (x, y, level, longitude, latitude) {
//             if (!this.ready) {
//                 throw new Cesium.DeveloperError('pickFeatures must not be called before the imagery provider is ready.');
//             }

//             if (!this.enablePickFeatures || !Cesium.defined(this._pickFeaturesUrl) || this._getFeatureInfoFormats.length === 0) {
//                 return undefined;
//             }

//             var formatIndex = 0;

//             var that = this;

//             function handleResponse(format, data) {
//                 return format.callback(data);
//             }

//             function doRequest() {
//                 if (formatIndex >= that._getFeatureInfoFormats.length) {
//                     // No valid formats, so no features picked.
//                     return when([]);
//                 }

//                 var format = that._getFeatureInfoFormats[formatIndex];
//                 var url = buildPickFeaturesUrl(that, x, y, level, longitude, latitude, format.format);

//                 ++formatIndex;

//                 function doXhrRequest(url) {
//                     return loadWithXhr({
//                         url: url,
//                         responseType: format.format
//                     }).then(handleResponse.bind(undefined, format)).otherwise(doRequest);
//                 }

//                 if (format.type === 'json') {
//                     return RequestScheduler.request(url, loadJson).then(format.callback).otherwise(doRequest);
//                 } else if (format.type === 'xml') {
//                     return RequestScheduler.request(url, loadXML).then(format.callback).otherwise(doRequest);
//                 } else if (format.type === 'text' || format.type === 'html') {
//                     return RequestScheduler.request(url, loadText).then(format.callback).otherwise(doRequest);
//                 } else {
//                     return RequestScheduler.request(url, doXhrRequest);
//                 }
//             }

//             return doRequest();
//         };

//         function buildImageUrl(imageryProvider, x, y, level) {
//             degreesScratchComputed = false;
//             projectedScratchComputed = false;

//             return buildUrl(imageryProvider, imageryProvider._urlParts, function (partFunction) {
//                 return partFunction(imageryProvider, x, y, level);
//             });
//         }

//         function buildPickFeaturesUrl(imageryProvider, x, y, level, longitude, latitude, format) {
//             degreesScratchComputed = false;
//             projectedScratchComputed = false;
//             ijScratchComputed = false;
//             longitudeLatitudeProjectedScratchComputed = false;

            
//             return buildUrl(imageryProvider, imageryProvider._pickFeaturesUrlParts, function (partFunction) {
//                 return partFunction(imageryProvider, x, y, level, longitude, latitude, format);
//             });
//         }

//         function buildUrl(imageryProvider, parts, partFunctionInvoker) {
//             var url = '';

//             for (var i = 0; i < parts.length; ++i) {
//                 var part = parts[i];
//                 if (typeof part === 'string') {
//                     url += part;
//                 } else {
//                     url += encodeURIComponent(partFunctionInvoker(part));
//                 }
//             }

//             var proxy = imageryProvider._proxy;
//             if (Cesium.defined(proxy)) {
//                 url = proxy.getURL(url);
//             }
//             console.log(url)    //创建最终的链接
//             return url;
//         }

//         function urlTemplateToParts(url, tags) {
//             if (!Cesium.defined(url)) {
//                 return undefined;
//             }

//             var parts = [];
//             var nextIndex = 0;
//             var minIndex;
//             var minTag;
//             var tagList = Object.keys(tags);

//             while (nextIndex < url.length) {
//                 minIndex = Number.MAX_VALUE;
//                 minTag = undefined;

//                 for (var i = 0; i < tagList.length; ++i) {
//                     var thisIndex = url.indexOf(tagList[i], nextIndex);
//                     if (thisIndex >= 0 && thisIndex < minIndex) {
//                         minIndex = thisIndex;
//                         minTag = tagList[i];
//                     }
//                 }

//                 if (!Cesium.defined(minTag)) {
//                     parts.push(url.substring(nextIndex));
//                     nextIndex = url.length;
//                 } else {
//                     if (nextIndex < minIndex) {
//                         parts.push(url.substring(nextIndex, minIndex));
//                     }
//                     parts.push(tags[minTag]);
//                     nextIndex = minIndex + minTag.length;
//                 }
//             }
//             return parts;
//         }

//         function padWithZerosIfNecessary(imageryProvider, key, value) {
//             if (imageryProvider &&
//                 imageryProvider.urlSchemeZeroPadding &&
//                 imageryProvider.urlSchemeZeroPadding.hasOwnProperty(key)) {
//                 var paddingTemplate = imageryProvider.urlSchemeZeroPadding[key];
//                 if (typeof paddingTemplate === 'string') {
//                     var paddingTemplateWidth = paddingTemplate.length;
//                     if (paddingTemplateWidth > 1) {
//                         value = (value.length >= paddingTemplateWidth) ? value : new Array(paddingTemplateWidth - value.toString().length + 1).join('0') + value;
//                     }
//                 }
//             }
//             return value;
//         }

//         function xTag(imageryProvider, x, y, level) {
//             return padWithZerosIfNecessary(imageryProvider, '{x}', x);
//         }

//         function reverseXTag(imageryProvider, x, y, level) {
//             var reverseX = imageryProvider.tilingScheme.getNumberOfXTilesAtLevel(level) - x - 1;
//             return padWithZerosIfNecessary(imageryProvider, '{reverseX}', reverseX);
//         }

//         function yTag(imageryProvider, x, y, level) {
//             return padWithZerosIfNecessary(imageryProvider, '{y}', y);
//         }

//         function reverseYTag(imageryProvider, x, y, level) {
//             var reverseY = imageryProvider.tilingScheme.getNumberOfYTilesAtLevel(level) - y - 1;
//             return padWithZerosIfNecessary(imageryProvider, '{reverseY}', reverseY);
//         }

//         function reverseZTag(imageryProvider, x, y, level) {
//             var maximumLevel = imageryProvider.maximumLevel;
//             var reverseZ = defined(maximumLevel) && level < maximumLevel ? maximumLevel - level - 1 : level;
//             return padWithZerosIfNecessary(imageryProvider, '{reverseZ}', reverseZ);
//         }

//         function zTag(imageryProvider, x, y, level) {
//             return padWithZerosIfNecessary(imageryProvider, '{z}', level);
//         }

//         function sTag(imageryProvider, x, y, level) {
//             var index = (x + y + level) % imageryProvider._subdomains.length;
//             return imageryProvider._subdomains[index];
//         }

//         var degreesScratchComputed = false;
//         var degreesScratch = new Rectangle();

//         function computeDegrees(imageryProvider, x, y, level) {
//             if (degreesScratchComputed) {
//                 return;
//             }

//             imageryProvider.tilingScheme.tileXYToRectangle(x, y, level, degreesScratch);
//             degreesScratch.west = CesiumMath.toDegrees(degreesScratch.west);
//             degreesScratch.south = CesiumMath.toDegrees(degreesScratch.south);
//             degreesScratch.east = CesiumMath.toDegrees(degreesScratch.east);
//             degreesScratch.north = CesiumMath.toDegrees(degreesScratch.north);

//             degreesScratchComputed = true;
//         }

//         function westDegreesTag(imageryProvider, x, y, level) {
//             computeDegrees(imageryProvider, x, y, level);
//             return degreesScratch.west;
//         }

//         function southDegreesTag(imageryProvider, x, y, level) {
//             computeDegrees(imageryProvider, x, y, level);
//             return degreesScratch.south;
//         }

//         function eastDegreesTag(imageryProvider, x, y, level) {
//             computeDegrees(imageryProvider, x, y, level);
//             return degreesScratch.east;
//         }

//         function northDegreesTag(imageryProvider, x, y, level) {
//             computeDegrees(imageryProvider, x, y, level);
//             return degreesScratch.north;
//         }

//         var projectedScratchComputed = false;
//         var projectedScratch = new Cesium.Rectangle();

//         function computeProjected(imageryProvider, x, y, level) {
//             if (projectedScratchComputed) {
//                 return;
//             }

//             imageryProvider.tilingScheme.tileXYToNativeRectangle(x, y, level, projectedScratch);

//             projectedScratchComputed = true;
//         }

//         function westProjectedTag(imageryProvider, x, y, level) {
//             computeProjected(imageryProvider, x, y, level);
//             return projectedScratch.west;
//         }

//         function southProjectedTag(imageryProvider, x, y, level) {
//             computeProjected(imageryProvider, x, y, level);
//             return projectedScratch.south;
//         }

//         function eastProjectedTag(imageryProvider, x, y, level) {
//             computeProjected(imageryProvider, x, y, level);
//             return projectedScratch.east;
//         }

//         function northProjectedTag(imageryProvider, x, y, level) {
//             computeProjected(imageryProvider, x, y, level);
//             return projectedScratch.north;
//         }

//         function widthTag(imageryProvider, x, y, level) {
//             return imageryProvider.tileWidth;
//         }

//         function heightTag(imageryProvider, x, y, level) {
//             return imageryProvider.tileHeight;
//         }

//         var ijScratchComputed = false;
//         var ijScratch = new Cartesian2();

//         function iTag(imageryProvider, x, y, level, longitude, latitude, format) {
//             computeIJ(imageryProvider, x, y, level, longitude, latitude);
//             return ijScratch.x;
//         }

//         function jTag(imageryProvider, x, y, level, longitude, latitude, format) {
//             computeIJ(imageryProvider, x, y, level, longitude, latitude);
//             return ijScratch.y;
//         }

//         function reverseITag(imageryProvider, x, y, level, longitude, latitude, format) {
//             computeIJ(imageryProvider, x, y, level, longitude, latitude);
//             return imageryProvider.tileWidth - ijScratch.x - 1;

//         }

//         function reverseJTag(imageryProvider, x, y, level, longitude, latitude, format) {
//             computeIJ(imageryProvider, x, y, level, longitude, latitude);
//             return imageryProvider.tileHeight - ijScratch.y - 1;
//         }

//         var rectangleScratch = new Rectangle();

//         function computeIJ(imageryProvider, x, y, level, longitude, latitude, format) {
//             if (ijScratchComputed) {
//                 return;
//             }

//             computeLongitudeLatitudeProjected(imageryProvider, x, y, level, longitude, latitude);
//             var projected = longitudeLatitudeProjectedScratch;

//             var rectangle = imageryProvider.tilingScheme.tileXYToNativeRectangle(x, y, level, rectangleScratch);
//             ijScratch.x = (imageryProvider.tileWidth * (projected.x - rectangle.west) / rectangle.width) | 0;
//             ijScratch.y = (imageryProvider.tileHeight * (rectangle.north - projected.y) / rectangle.height) | 0;
//             ijScratchComputed = true;
//         }

//         function longitudeDegreesTag(imageryProvider, x, y, level, longitude, latitude, format) {
//             return CesiumMath.toDegrees(longitude);
//         }

//         function latitudeDegreesTag(imageryProvider, x, y, level, longitude, latitude, format) {
//             return CesiumMath.toDegrees(latitude);
//         }

//         var longitudeLatitudeProjectedScratchComputed = false;
//         var longitudeLatitudeProjectedScratch = new Cartesian3();

//         function longitudeProjectedTag(imageryProvider, x, y, level, longitude, latitude, format) {
//             computeLongitudeLatitudeProjected(imageryProvider, x, y, level, longitude, latitude);
//             return longitudeLatitudeProjectedScratch.x;
//         }

//         function latitudeProjectedTag(imageryProvider, x, y, level, longitude, latitude, format) {
//             computeLongitudeLatitudeProjected(imageryProvider, x, y, level, longitude, latitude);
//             return longitudeLatitudeProjectedScratch.y;
//         }

//         var cartographicScratch = new Cartographic();

//         function computeLongitudeLatitudeProjected(imageryProvider, x, y, level, longitude, latitude, format) {
//             if (longitudeLatitudeProjectedScratchComputed) {
//                 return;
//             }

//             var projected;
//             if (imageryProvider.tilingScheme instanceof GeographicTilingScheme) {
//                 longitudeLatitudeProjectedScratch.x = CesiumMath.toDegrees(longitude);
//                 longitudeLatitudeProjectedScratch.y = CesiumMath.toDegrees(latitude);
//             } else {
//                 var cartographic = cartographicScratch;
//                 cartographic.longitude = longitude;
//                 cartographic.latitude = latitude;
//                 projected = imageryProvider.tilingScheme.projection.project(cartographic, longitudeLatitudeProjectedScratch);
//             }

//             longitudeLatitudeProjectedScratchComputed = true;
//         }

//         function formatTag(imageryProvider, x, y, level, longitude, latitude, format) {
//             return format;
//         }

//         var tags = {
//             '{x}': xTag,
//             '{y}': yTag,
//             '{z}': zTag,
//             '{s}': sTag,
//             '{reverseX}': reverseXTag,
//             '{reverseY}': reverseYTag,
//             '{reverseZ}': reverseZTag,
//             '{westDegrees}': westDegreesTag,
//             '{southDegrees}': southDegreesTag,
//             '{eastDegrees}': eastDegreesTag,
//             '{northDegrees}': northDegreesTag,
//             '{westProjected}': westProjectedTag,
//             '{southProjected}': southProjectedTag,
//             '{eastProjected}': eastProjectedTag,
//             '{northProjected}': northProjectedTag,
//             '{width}': widthTag,
//             '{height}': heightTag
//         };

//         var pickFeaturesTags = Ceaium.combine(tags, {
//             '{i}': iTag,
//             '{j}': jTag,
//             '{reverseI}': reverseITag,
//             '{reverseJ}': reverseJTag,
//             '{longitudeDegrees}': longitudeDegreesTag,
//             '{latitudeDegrees}': latitudeDegreesTag,
//             '{longitudeProjected}': longitudeProjectedTag,
//             '{latitudeProjected}': latitudeProjectedTag,
//             '{format}': formatTag
//         });
